package demo.threadpool;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;

import com.hissy.common.cache.Func;
import org.junit.Test;

/**
 * Created by zhangyanfei on 2018/11/12.
 *
 * @author zhangyanfei
 * @date 2018/11/12
 */
public class CacheServiceCopy {
    //任务队列
    private static final LinkedBlockingQueue<Runnable> REFRESH_WORKING_QUEUE = new LinkedBlockingQueue<>(256);
    /**
     * 异步更新线程池
     */
    private static final ThreadPoolExecutor CACHE_REFRESH_EXECUTOR = new ThreadPoolExecutor(4, 16, 30, TimeUnit.SECONDS,
        REFRESH_WORKING_QUEUE, new ThreadFactory() {
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private static final String NAME_PREFIX = "cacheRefreshPool-t-";

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(Thread.currentThread().getThreadGroup(), r,
                NAME_PREFIX + threadNumber.getAndIncrement(), 0);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            return t;
        }
    }, (r, executor) -> {
        System.out.println("rejected cache key:" + r.toString());
    });

    /**
     * 更新任务
     */
    public static class CacheRefreshTask implements Runnable {
        private final String cacheKey;
        private final int hashCode;
        private final Runnable task;

        CacheRefreshTask(String cacheKey, Runnable task) {
            if (cacheKey == null || task == null) {
                throw new NullPointerException("cache key or task is null");
            }
            this.cacheKey = cacheKey;
            this.task = task;
            hashCode = cacheKey.hashCode();
        }

        @Override
        public void run() {
            task.run();
        }

        @Override
        public int hashCode() {
            return hashCode;
        }

        @Override
        public boolean equals(Object obj) {
            return obj != null && hashCode == obj.hashCode() && (obj instanceof CacheRefreshTask) && this.cacheKey
                .equals(((CacheRefreshTask)obj).cacheKey);
        }

        @Override
        public String toString() {
            return cacheKey;
        }
    }

    /**
     * @param namespace             命名空间
     * @param key                   key
     * @param logicalExpireSeconds  逻辑过期时间
     * @param physicalExpireSeconds 物理过期时间
     * @param cacheNullable         缓存对象能否为空
     * @param func                  缓存对象刷新回调
     * @param clazz                 缓存对象类
     * @param lock                  线程安全锁
     * @param <T>                   回调返回类型
     * @return
     */
    public <T> T cache(String namespace, String key, int logicalExpireSeconds, int physicalExpireSeconds,
                       boolean cacheNullable, Func<T> func, Class<T> clazz, Lock lock) {

        return null;
    }

    /**
     * 刷新缓存
     *
     * @param realKey
     * @param object
     * @param logicalExpireSeconds
     * @param physicalExpireSeconds
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> boolean refreshCache(String realKey, T object, int logicalExpireSeconds, int physicalExpireSeconds,
                                    Class<T> clazz) {
        return true;
    }

    /**
     * 异步
     *
     * @param realKey
     * @param logicalExpireSeconds
     * @param physicalExpireSeconds
     * @param cacheNullable
     * @param func
     * @param tClass
     * @param lock
     * @param <T>
     */
    private <T> void asyncReload(String realKey, int logicalExpireSeconds, int physicalExpireSeconds,
                                 boolean cacheNullable, Func<T> func, Class<T> tClass, Lock lock) {
        try {
            //并发锁
            try {
                // 业务
            } finally {

            }
        } catch (Exception e) {

        }
    }

    @Test
    public void test_C1() throws InterruptedException {

        for (int i = 0; i < 10; i++) {
            // 异步执行
            CACHE_REFRESH_EXECUTOR.execute(new CacheRefreshTask("Demo", () -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("refresh xxx");
            }));
        }
        System.out.println("start");

        Thread.sleep(10000);
    }

}
